/*
 *  @author kszyh
 *  @version $Id$
 */
package bt;

import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.bluetooth.*;
import net.sf.bluecove.obex.RemoteDeviceExt;

/** Klasa służy do wykrywania pobliskich urzadzen pikosieci BlueTooth */
public class Finder implements DiscoveryListener {

    private static final int MAJOR_DEVICE_CLASS_PHONE = 0x0200;
    private Vector Urzadzenia = new Vector();
    private Vector Uslugi = new Vector();
    private DiscoveryAgent discoveryAgent;
    private final String serviceUUID;
    private static final int SERVICE_NAME_BASE_LANGUAGE = 0x0100;
    private final int serviceAttributes[] = {SERVICE_NAME_BASE_LANGUAGE};
    private Vector transIds = new Vector();
    String serviceURL;
    public final UUID OBEX = new UUID(0x0008);
    public final UUID OBEX_OBJECT_PUSH = new UUID(0x1105);
    public final UUID OBEX_FILE_TRANSFER = new UUID(0x1106);
    int servicesSearchTransID = 0;



    // służa zarządzania watkami //
    // final Object inquiryCompletedEvent = new Object();
    final Object serviceSearchCompletedEvent = new Object();
    boolean started = false;
    int actThreads = 0;
    private boolean inquiryInProgress = false;

    public Finder(String serviceUUID) {
        this.serviceUUID = serviceUUID;
        szukarka();
    }

    public String getUrlFromIndex(int i) {
        if (i >= Urzadzenia.size()) {
            return "Brak danych";
        }
        RemoteDevice btDevice = (RemoteDevice) Urzadzenia.get(i);
        String adres = btDevice.getBluetoothAddress();
        return adres;
    }

    private void szukarka() {
        try {
            discoveryAgent = LocalDevice.getLocalDevice().getDiscoveryAgent();
        } catch (Exception e) {
            String blad = "Bład podczas pobierania właściwości lokalnego urządzenia: " + e.getMessage();
            System.out.println(blad);
        }

        try {
            started = discoveryAgent.startInquiry(DiscoveryAgent.LIAC, this);
        } catch (BluetoothStateException e) {
            String blad = "Błąd podczas wyszukiwania: " + e.getMessage();
            System.out.println(blad);
        }

    }

            public boolean startServiceSearch(RemoteDevice device, UUID obexUUID) {
                serviceURL = null;
                try {
                        UUID[] searchUuidSet = new UUID[] { obexUUID };
                        int[] attrIDs = new int[] { 0x0100 };
                        //serviceSearchOn = getFriendlyName(device);
                        servicesSearchTransID = LocalDevice.getLocalDevice().getDiscoveryAgent().searchServices(attrIDs,
                                        searchUuidSet, device, this);
                } catch (Throwable e) {
                     //   Logger.error(e);
                     //   mainInstance.setStatus("Cannot start inquiry " + e.getMessage());
                        return false;
                }
                return servicesSearchTransID != 0;
        }


         public boolean searching() {
                return servicesSearchTransID != 0;
        }

        // Wyszukuje usluge Obex  na urzadzeniu   
          public String findOBEX(String btAddress) {
                RemoteDevice device = new RemoteDeviceExt(btAddress);
                serviceURL = null;
                if (!startServiceSearch(device, OBEX_OBJECT_PUSH)) {
                       Main.form1.jStatusBar1.setMessage("Nie można wysłać pliku");
                } else {
                        while (searching()) {
                                try {
                                        Thread.sleep(1000);
                                } catch (Exception e) {
                                }
                        }
                }
                if (serviceURL == null) {
                        if (!startServiceSearch(device, OBEX_FILE_TRANSFER)) {
                       Main.form1.jStatusBar1.setMessage("Nie można wysłać pliku");
                        } else {
                                while (searching()) {
                                        try {
                                                Thread.sleep(1000);
                                        } catch (Exception e) {
                                        }
                                }
                        }
                }
                return serviceURL;
        }



    public void przerwijSzukanieUrzadzen() {
        discoveryAgent.cancelInquiry(this);

    }

    public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
        // sprawdzamy czy to telefon
        if (cod.getMajorDeviceClass() == MAJOR_DEVICE_CLASS_PHONE) {
            // by nie wprowadzac duplikatow
            if (Urzadzenia.contains(btDevice) == false) {
                Urzadzenia.addElement(btDevice);
                System.out.println("Urządzenie " + Urzadzenia.size() + ": " + btDevice.getBluetoothAddress());
                try {
                    System.out.println("              nazwa:   " + btDevice.getFriendlyName(false));
                    Main.form1.addToList(btDevice.getFriendlyName(false),0);
                } catch (IOException cantGetDeviceName) {
                    System.out.println("Nie można uzyskać nazwy urządzenia.");
                }
            }
        }
    }

    public void inquiryCompleted(int discType) {
        System.out.println("Wykrywanie zakończone!");
        Main.form1.setStatusBarText("Wykrywanie usług... Proszę czekać.");
       // setInquiryInProgress(true);
        //===========================================================
        UUID[] serviceUidsToSearch = new UUID[]{new UUID(serviceUUID, false)};

        if(Urzadzenia.size() == 0) {
            Main.form1.changeB2Name();
            Main.form1.jStatusBar1.setMessage("Nie wykryto żadnych urządzeń w pobliżu!");
            return;

        }
        if (discType == INQUIRY_COMPLETED) {
            if (Urzadzenia.size() != 0) {
                actThreads = Urzadzenia.size(); // do synchronizacji watkow //

                for (int i = 0; i < Urzadzenia.size(); i++) {
                    try {
                        //int transId =
                        discoveryAgent.searchServices(serviceAttributes, serviceUidsToSearch, (RemoteDevice) Urzadzenia.elementAt(i), this);
                        //transIds.addElement(new Integer(transId));

                    } catch (BluetoothStateException e) {
                        System.out.println("Wyszukiwanie uslug sie zjebalo: " + e.getMessage());
                    } catch (Exception e) {
                    }
                }

            }
        }
    }

    private synchronized void setInquiryInProgress(boolean bool) {
        inquiryInProgress = bool;
    }

    boolean cancelPendingSearches() {
        boolean everythingCancelled = true;

        if (inquiryInProgress) {
            // Note: The BT API (v1.0) isn't completely clear
            // whether cancelInquiry is blocking or non-blocking.

            if (discoveryAgent.cancelInquiry(this)) {
                setInquiryInProgress(false);
            } else {
                everythingCancelled = false;
            }
        }

        for (int i = 0; i < transIds.size(); i++) {
            // Note: The BT API (v1.0) isn't completely clear
            // whether cancelServiceSearch is blocking or
            // non-blocking?

            Integer pendingId =
                    (Integer) transIds.elementAt(i);
            if (discoveryAgent.cancelServiceSearch(
                    pendingId.intValue())) {
                transIds.removeElement(pendingId);
            } else {
                everythingCancelled = false;
            }
        }
        return everythingCancelled;
    }

    // metoda wywoływana na zakończenie wyszukiwania  serwisów
    public void serviceSearchCompleted(int transID, int respCode) {
        actThreads--;
        if (actThreads == 0) {
            synchronized (serviceSearchCompletedEvent) {
                System.out.println("Zakończono wyszukiwanie usług.");
                Main.form1.setStatusBarText("Zakończono wyszukiwanie usług.");
                Main.form1.changeB2Name();
                for (int i = 0; i < Uslugi.size(); i++) {
                ServiceRecord sr = (ServiceRecord) Uslugi.elementAt(i);
                 DataElement de = sr.getAttributeValue(SERVICE_NAME_BASE_LANGUAGE);
                 String name = (String) de.getValue();
                 Main.form1.setItemAsClient(name);
                serviceSearchCompletedEvent.notifyAll();

            }
        }
    }
    }

    //====================================

    // metoda wywoływana, gdy serwis zostanie znaleziony
    public void wyszukajUslugi() throws InterruptedException {
        synchronized (serviceSearchCompletedEvent) {
            serviceSearchCompletedEvent.wait();
        }

        // czekanie na zakonczenie wszytskich watkow wyszukiwania...
        System.out.println("Znaleziono " + Uslugi.size() + " klientów.");

    }

    public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
        Uslugi.addElement(servRecord[0]);
    }

    /*
     *Zwraca Urzadzenia na ktorych działaja usługi, ktorych nazwy pasuja do wektora nazw przeslanych
     */
    public Vector selectS(Vector names) {
        Vector devs = new Vector();

        for (int i = 0; i < Uslugi.size(); i++) {
           ServiceRecord sr = (ServiceRecord) Uslugi.elementAt(i);
           DataElement de = sr.getAttributeValue(SERVICE_NAME_BASE_LANGUAGE);
           String nick = (String) de.getValue();

           if(names.contains(nick)){
           devs.addElement(Uslugi.elementAt(i));
           }

        }

        return devs;
    }

    public String Whois(String names){
        RemoteDevice dev = null;
        String nick = new String();
        String url = new String();
        for(int i = 0; i < Urzadzenia.size(); i++){
            RemoteDevice btDevice = (RemoteDevice)Urzadzenia.elementAt(i);
            try {
                nick = btDevice.getFriendlyName(false);
            } catch (Exception ex) {
            }
            if(names.equals(nick))
            dev = btDevice;
            url = dev.getBluetoothAddress();


        }
        return url;
    }

      public void shutdown() {
        try {
            LocalDevice.getLocalDevice().getDiscoveryAgent().cancelInquiry(this);
        } catch (Exception ex) {
            //Logger.getLogger(Finder.class.getName()).log(Level.SEVERE, null, ex);
        }


        }


    //=================================================
};